////////////////////////////////////////////////////////////////////////////////
//
//	This file is part of Woozox, see <http://code.google.com/p/woozox/>.
//
//	Copyright 2008-2009 Florian David
//
//	Woozoo is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Lesser General Public License as 
//	published by the Free Software Foundation, either version 3 of 
//	the License, or (at your option) any later version.
//
//	Woozoo is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public 
//	License along with Woozoo. If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
package org.woozoo.xhtml.core.base.selector
{
	/**
	 * @private
	 * */	
	internal class SelectorOperatorFactory
	{
		private static const REG_STRING_INT : String = '[-a-zA-Z0-9]+';
		private static const REG_START : String = '^';
		private static const REG_STOP : String = '$';
		private static const REG_NUM : String = '[-+n0-9]+|even|odd';
		private static const REG_ALL_EXCEPT_BRACKET : String = '[^\\]]+';
		private static const REG_ALL_EXCEPT_QUOTE : String = '[^"]+';
		private static const REG_ONE_OR_MORE_SPACE : String = '[ ]*';
		
		public static const SELECTOR_UNIT : Array = 
													[
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\.' + REG_STRING_INT + REG_STOP), 	// ".class"			0
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '[\\*a-zA-Z0-9]+' + REG_STOP), 		// "div" or "*"
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '#' + REG_STRING_INT + REG_STOP), 	// "#myId"
														new RegExp(REG_START + '>' + REG_STRING_INT + REG_STOP), 	// ">ul"
														new RegExp(REG_START + '~' + REG_STRING_INT + REG_STOP), 	// "~ul"			
														new RegExp(REG_START + '\\+' + REG_STRING_INT + REG_STOP), 	// "+ul"
														new RegExp(REG_START + ':first-of-type' + REG_STOP), 		// :first-of-type
														new RegExp(REG_START + ':first-child' + REG_STOP), 			// :first-child
														new RegExp(REG_START + ':last-of-type' + REG_STOP), 		// :last-of-type
														new RegExp(REG_START + ':last-child' + REG_STOP), 			// :last-child	
														new RegExp(REG_START + ':only-child' + REG_STOP), 			// :only-child
														new RegExp(REG_START + ':only-of-type' + REG_STOP), 		// :only-of-type
														new RegExp(REG_START + ':nth-child\\('+REG_NUM+'\\)' + REG_STOP), 	
														new RegExp(REG_START + ':nth-last-child\\('+REG_NUM+'\\)' + REG_STOP),
														new RegExp(REG_START + ':nth-last-of-type\\('+REG_NUM+'\\)' + REG_STOP), //			
														new RegExp(REG_START + ':nth-of-type\\('+REG_NUM+'\\)' + REG_STOP),
														new RegExp(REG_START + ':empty' + REG_STOP),
														new RegExp(REG_START + ':target' + REG_STOP),
														new RegExp(REG_START + ':lang\\('+REG_STRING_INT+'\\)' + REG_STOP),
														new RegExp(REG_START + '::first-line' + REG_STOP),	// 							
														new RegExp(REG_START + '::first-letter' + REG_STOP),
														new RegExp(REG_START + ':root' + REG_STOP),
														new RegExp(REG_START + ':not\\([:# \\.\\*a-zA-Z0-9]+\\)' + REG_STOP),
														
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\|=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title|=myTitle]" 	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\]' + REG_STOP), // "[title]"										
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title=myTitle]"
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\^=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title^=myTitle]"	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\$=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title$=myTitle]"	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\*=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title*=myTitle]"		
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '~=' + REG_ALL_EXCEPT_BRACKET + '\\]' + REG_STOP), // "[title~=myTitle]"		

														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\|="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP), // "[title|=myTitle]" 	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP), // "[title=myTitle]"
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\^="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP), // "[title^=myTitle]"	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\$="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP), // "[title$=myTitle]"	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '\\*="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP), // "[title*=myTitle]" 	
														new RegExp(REG_START + REG_ONE_OR_MORE_SPACE + '\\[' + REG_STRING_INT + '~="' + REG_ALL_EXCEPT_QUOTE + '"\\]' + REG_STOP) // "[title~=myTitle]"	
													];
		
		public static function factory(index : int) : ISelectorOperator {
			var k : Class;
			switch (index) {
				case 0: k = SelectorOperatorPoint; break;
				case 1: k = SelectorOperatorSpace; break;
				case 2: k = SelectorOperatorPound; break;
				case 3: k = SelectorOperatorGreater; break;
				case 4: k = SelectorOperatorTild; break;
				case 5: k = SelectorOperatorPlus; break;
				case 6: k = SelectorOperatorFirstOfType; break;
				case 7: k = SelectorOperatorFirstChild; break;
				case 8: k = SelectorOperatorLastOfType; break;
				case 9: k = SelectorOperatorLastChild; break;
				case 10: k = SelectorOperatorOnlyChild; break;
				case 11: k = SelectorOperatorOnlyOfType; break;
				case 12: k = SelectorOperatorNthChild; break;
				case 13: k = SelectorOperatorNthLastChild; break;
				case 14: k = SelectorOperatorNthLastOfType; break;
				case 15: k = SelectorOperatorNthOfType; break;
				case 16: k = SelectorOperatorEmpty; break;
				case 17: k = SelectorOperatorTarget; break;
				case 18: k = SelectorOperatorLang; break;
				case 19: k = SelectorOperatorFirstLine; break;
				case 20: k = SelectorOperatorFirstLetter; break;
				case 21: k = SelectorOperatorRoot; break;
				case 22: k = SelectorOperatorNot; break;
				case 23: case 30: k = SelectorOperatorAttrContainsHiphenSeparated; break;
				case 24: k = SelectorOperatorHasAttr; break;
				case 25: case 31: k = SelectorOperatorAttrEqualTo; break;
				case 26: case 32: k = SelectorOperatorAttrStartWith; break;
				case 27: case 33: k = SelectorOperatorAttrEndWith; break;
				case 28: case 34: k = SelectorOperatorAttrContains; break;
				case 29: case 35: k = SelectorOperatorAttrContainsWhitespaceSeparated; break;
				default: 
					throw new Error('SelectorOperatorFactory::factory : Unknow index '+index);
				break;
			}
			return new k();
		}
	}
}